//                 _              
//                | |             
//   __ _ _ __ ___| |__ __  _____ 
//  / _` | '__/ __| '_ \\ \/ / __|
// | (_| | | | (__| | | |>  <\__ \
//  \__,_|_|  \___|_| |_/_/\_\___/
//                                
// Copyright 2010 Scott Dixon http://www.archxs.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package com.archxs.commons;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.LinkedList;
import java.util.Locale;
import java.util.Queue;

import org.junit.Assert;
import org.junit.Test;

import com.archxs.commons.Variant;
import com.archxs.commons.VariantObjectCache;
import com.archxs.commons.VariantObjectCacheDefault;
import com.archxs.commons.VariantObjectCacheFactory;

/**
 * Tests of the {@link VariantObjectCacheDefault} implementation of {@link VariantObjectCache}
 */
public class VariantObjectCacheDefaultTest {

    @Test
    public void testObjectCacheCleanup() {
        VariantObjectCacheFactory.getInstance().clearCache();
        final Locale locale = Locale.GERMANY;
        final Queue<Reference<Variant> > fakeExpiredReferences = new LinkedList<Reference<Variant> >();
        final ReferenceQueue<Variant> mockReferenceQueue = new ReferenceQueue<Variant>() {
            @Override
            public Reference<? extends Variant> poll() {
                return fakeExpiredReferences.poll();
            }
        };
        final VariantObjectCacheDefault testSubject = new VariantObjectCacheDefault(mockReferenceQueue);
        final int testSize = 10;
        final Variant[] strongRefs = new Variant[testSize];
        for(int i = 0; i < testSize; ++i) {
            strongRefs[i] = testSubject.readThroughCache(Variant.class, "0x" + Integer.toHexString(i), locale);
        }
        Assert.assertEquals(testSize, testSubject.getCacheSize());
        for(final Variant strongRef : strongRefs) {
            fakeExpiredReferences.add(testSubject.getReferenceHelper(strongRef.toString(), locale));
        }
        Assert.assertTrue(testSubject.cleanupCache(null));
        Assert.assertEquals(0, fakeExpiredReferences.size());
        Assert.assertEquals(0, testSubject.getCacheSize());
    }
    
    @Test
    public void testObjectCacheCleanupInChunks() {
        VariantObjectCacheFactory.getInstance().clearCache();
        final Locale locale = Locale.CHINA;
        final Queue<Reference<Variant> > fakeExpiredReferences = new LinkedList<Reference<Variant> >();
        final ReferenceQueue<Variant> mockReferenceQueue = new ReferenceQueue<Variant>() {
            @Override
            public Reference<? extends Variant> poll() {
                return fakeExpiredReferences.poll();
            }
        };
        final VariantObjectCacheDefault testSubject = new VariantObjectCacheDefault(mockReferenceQueue);
        final int testSize = 10;
        final Variant[] strongRefs = new Variant[testSize];
        for(int i = 0; i < testSize; ++i) {
            strongRefs[i] = testSubject.readThroughCache(Variant.class, "0x" + Integer.toHexString(i), locale);
        }
        Assert.assertEquals(testSize, testSubject.getCacheSize());
        for(final Variant strongRef : strongRefs) {
            fakeExpiredReferences.add(testSubject.getReferenceHelper(strongRef.toString(), locale));
        }
        Assert.assertTrue(testSubject.cleanupCache(new Object[(testSize / 2) + 2]));
        Assert.assertEquals(0, fakeExpiredReferences.size());
        Assert.assertEquals(0, testSubject.getCacheSize());
    }
    
}
